/**
* Created by chenly on 12/27/23.
* Description
**/

#include <iostream>
#include "httplib.h"
#include "json.hpp"
#include <gflags/gflags.h>

using namespace std;

DEFINE_string(remote_call, "AllInstruments", "remote call");
DEFINE_string(host, "127.0.0.1:8080", "Server host");
DEFINE_string(InstrumentID, "IC2401", "Market call param");
DEFINE_bool(print, false, "Print the response");
DEFINE_bool(bench, false, "benchmark");

class Stat {
public:
    void finished_single_op(int counter = 1) {
        m_done+=counter;
        if (m_done >= m_next_report) {
            if (m_next_report < 1000)
                m_next_report += 100;
            else if (m_next_report < 5000)
                m_next_report += 500;
            else if (m_next_report < 10000)
                m_next_report += 1000;
            else if (m_next_report < 50000)
                m_next_report += 5000;
            else if (m_next_report < 100000)
                m_next_report += 10000;
            else if (m_next_report < 500000)
                m_next_report += 50000;
            else
                m_next_report += 100000;
            int ret = m_done.load();
            std::fprintf(stderr, "... finished %d ops%30s\r", ret, "");
            std::fflush(stderr);
        }
    }

public:

    std::atomic<int> m_done = 0;
    int m_next_report = 100;
};

void print_benchmark_result(const char *func_name, int time_cost, Stat &stat) {
    cout.setf(ios::left);
    std::cout << std::setw(32) << func_name << " : " << stat.m_done / (double) time_cost * 1000 << " op/s" << " total:"
              << stat.m_done << " timecost:" << time_cost << " ms" << std::endl;
}

void bench_get_market() {
    httplib::Client cli("http://" + FLAGS_host);
    httplib::Result res;
    Stat stat;
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < 1000; ++i) {
        httplib::Headers headers;
        headers.emplace(std::make_pair("InstrumentID", FLAGS_InstrumentID));
        res = cli.Get("/" + FLAGS_remote_call, headers);
        stat.finished_single_op();
    }
    auto elapsed = std::chrono::high_resolution_clock::now() - start;
    int time_cost = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
    print_benchmark_result(__FUNCTION__, time_cost, stat);
}

int main(int argc, char *argv[]) {
    google::ParseCommandLineFlags(&argc, &argv, true);

    if(FLAGS_bench){
        bench_get_market();
    } else{
        httplib::Client cli("http://" + FLAGS_host);
        httplib::Result res;
        if (FLAGS_remote_call == "AllInstruments") {
            res = cli.Get("/" + FLAGS_remote_call);
        } else if (FLAGS_remote_call == "Market") {
            httplib::Headers headers;
            headers.emplace(std::make_pair("InstrumentID", FLAGS_InstrumentID));
            res = cli.Get("/" + FLAGS_remote_call, headers);
        } else{
            std::cerr << "Unknown call.." << FLAGS_remote_call <<endl;
            return -1;
        }

        if (res.error() != httplib::Error::Success) {
            cout << "Get failed " <<endl;
        } else {
            cout << "status=" << res->status <<endl;
            if(FLAGS_print){
                cout<< " Res body=" << res->body << endl;
            }
        }
    }

    return 0;
}

